Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

An alternate approach to enums #930

Draft
wants to merge 1 commit into
base: main
Choose a base branch
from
Draft

An alternate approach to enums #930

wants to merge 1 commit into from

Conversation

toddburnside
Copy link
Contributor

This PR is meant as a topic for discussion.

The "dynamic enums" work well for enumerations that we think might change with some frequency in the future. However, they are more cumbersome to use, especially on the ODB side where we need to treat them as Tags and convert to enumerations when desired.

For enumerations that are unlikely to change, or will change infrequently, the value of the dynamic approach seems questionable. This PR presents a possible alternate solution to making sure that "static" enumerations defined in Scala match the values defined in a Postgres enum and in the GraphQL API. To me, this seems to be a simpler alternative to the dyamic implementation for enums like ProposalStatus, ObsAttachmentType and ProposalAttachmentType.

// enums defined in scala for which we want to validate the postgres enums and add to the schema
val scalaEnums: List[ScalaEnum] =
List(
ScalaEnum("e_too_activation", Enumerated[ToOActivation].toEnumType("ToOActivation", "Target of Opportunity Activation")(_.label))
Copy link
Contributor Author

@toddburnside toddburnside Jan 22, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The description string ("Target of Opportunity Activiation") doesn't seem to be actually be used for anything? It would be nice if it could be the comment for the enum itself in the schema.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

However, we can add comments before the DUMMY entries in OdbSchema.graphql and they will be retained in the final schema.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What happens if the validation with postgres fails?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The service doesn't start. Same thing as if there is a problem loading the dynamic enums.

@cquiroz
Copy link
Contributor

cquiroz commented Jan 23, 2024

Is the idea that enums thta change more often, e.g. Filters would remain in the db while those that don't e.g. SIte will remain as code?

@toddburnside
Copy link
Contributor Author

Is the idea that enums thta change more often, e.g. Filters would remain in the db while those that don't e.g. SIte will remain as code?

Yes, that is what I was thinking.

And, Shane has informed me that ToOActivation may be a bad example. 😆 It appears that Bryan is poised to complicate the TOO process a bit.

@swalker2m
Copy link
Contributor

I like having the option, and working with actual Scala enums is much easier. Seeing Tag in the code instead of actual enumeration values feels wrong. Still, if there is much of a chance that an enum will be updated it will be problematic if we have to simultaneously update all the services and clients when a new value is added or removed. I guess you're saying those remain dynamic though.

val scalaValues = scalaEnum.enumType.enumValues.map(_.name.toLowerCase)
s.unique(query.query(_text_enum)).flatMap(l =>
// May need to allow for different ordering and conversions
if (l === scalaValues) Monad[F].unit
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

raiseUnless ?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice.

@rpiaggio
Copy link
Contributor

I'm going to take a step back here and reevaluate our approach to dynamic enums. Now that we have them in place, they seem overly complicated to me. They require thinking of the instance and the meta level when programming. Furthermore, in several places we want our code to react to specific instances and referring to them is unsafe, we are assuming their existence and the compiler can't check that.

My opinion is to roll back dynamic enums. Let the source of truth be Scala enums. We are building web systems, in part, because they are easy and straightforward to redeploy. So, when we add an enum instance, we can press a button and redeploy everything. If we really want Postgres enums in the DB to represent them, we can generate migrations from the Scala enums.

Alternatively, we could have Postgres be the source of truth and generate Scala code from that, like we did before. But I'd rather have Scala be the source of truth for the simple reason that lucuma-odb is upstream in the dependency chain.

If we have an "enum" that changes frequently enough that it becomes tedious to redeploy because of it, then maybe it should be its own entity (eg: *Filter).

@tpolecat
Copy link
Member

I need some time to think about this. Thanks for your patience.

@toddburnside
Copy link
Contributor Author

I want to be clear that the purpose of this PR is to spur discussion. Like Raúl, I'm skeptical of the value of the dynamic enums given their complexity, but am amenable to having some of them dynamic if that it seems best. However, I'd prefer if we didn't use dynamic enums for everything. For example, all of the dynamic enums I have created (ProposalStatus, ObsAttachmentType and ProposalAttachmentType) don't really seem to need to be dynamic. I don't care if it is an approach similar to the one in this PR, or something different, but I'd like to be able to use scala enumerations where possible.

@swalker2m
Copy link
Contributor

FWIW I spent some time figuring out why this was evaluating true in some PL/pgSQL code ...

    IF NEW.c_proposal_status <> 'not_submited'::d_tag THEN

I think if it had been an enum instead it would have been obvious.

@cquiroz
Copy link
Contributor

cquiroz commented Mar 18, 2024

What's the state of this discussion?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants